﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Classes_and_Interfaces.Exceptions;
using Classes_and_Interfaces.SupportClasses;

namespace Classes_and_Interfaces.SupportClasses
{
	class PossibleHarmonyStupensForNoteMaker
	{
        //получение списка номеров ступеней, котоыре можно использовать в данном аккорде
        //в списке ПЕРВЫЙ ЭЛЕМЕНТ - ЭТО СТУПЕНЬ НОТЫ В БАСОВОМ ГОЛОСЕ, т.к. бас всегда точно определен из функции
        public static List<int> make(Note ourNote, int basis, string function)
        {
            List<int> possibleStupens = new List<int>();
            switch (function)
            {
                case "53":
                    //формируем список номеров ступеней, которые МОЖНО использовать 
                    possibleStupens.Add(basis);
                    possibleStupens.Add(basis);
                    possibleStupens.Add((basis + 2) % 7);
                    possibleStupens.Add((basis + 4) % 7);
                    break;
                case "6":
                    //ВАРИАНТ С УДВОЕНИЕМ ТЕРЦОВОГО ТОНА: (НЕ УДАЛЯТЬ, РАБОТАЕТ!)
                    //    //если oN не в басу и при этом является терцовым тоном, то ошибка в выборе функции
                    //    if ((ourNote.getStupen() == ((basis + 2) % 7)) && (ourNote.getVoice() != BASS))
                    //       throw new NotRightHarmonyException();
                    //    //формируем список номеров ступеней, которые МОЖНО использовать 
                    //    possibleStupens.Add((basis + 2) % 7);    
                    //    possibleStupens.Add(basis);
                    //    possibleStupens.Add((basis + 2) % 7);
                    //    possibleStupens.Add((basis + 4) % 7);  

                    //ВАРИАНТ БЕЗ УДВОЕНИЯ ТЕРЦОВОГО ТОНА:
                    //если oN не в басу и при этом является терцовым тоном, то ошибка в выборе функции
                    if ((ourNote.getStupen() == ((basis + 2) % 7)) && (ourNote.getVoice() != Constants.BASS))
                        throw new NotRightHarmonyException();
                    //формируем список номеров ступеней, которые МОЖНО использовать
                    possibleStupens.Add((basis + 2) % 7);
                    possibleStupens.Add(basis);
                    possibleStupens.Add(basis);
                    possibleStupens.Add((basis + 4) % 7);
                    possibleStupens.Add((basis + 4) % 7);
                    break;
                case "64":
                    //АКСИОМА: квинтовый тон в квартсекстах есть только в басу 
                    if ((ourNote.getStupen() == ((basis + 4) % 7)) && (ourNote.getVoice() != Constants.BASS))    // С ТОЧКИ ЗРЕНИЯ
                        throw new NotRightHarmonyException();
                    //формируем массив под номера ступеней, которые МОЖНО использовать                    
                    possibleStupens.Add((basis + 4) % 7);
                    possibleStupens.Add(basis);
                    possibleStupens.Add(basis);
                    possibleStupens.Add((basis + 2) % 7);
                    break;
                case "7":
                    //если oN не в басу, но при этом занимает ступень, что должна быть в басу,
                    //то значит, мы не правильно подобрали функцию  
                    if ((ourNote.getVoice() != Constants.BASS) && (ourNote.getStupen() == basis))
                        throw new NotRightHarmonyException();
                    possibleStupens.Add(basis);
                    possibleStupens.Add((basis + 2) % 7);
                    possibleStupens.Add((basis + 4) % 7);
                    possibleStupens.Add((basis + 6) % 7);
                    break;
                case "65":
                    //если oN не в басу, но при этом занимает ступень, что должна быть в басу,
                    //то значит, мы не правильно подобрали функцию  
                    if ((ourNote.getVoice() != Constants.BASS) && (ourNote.getStupen() == ((basis + 2) % 7)))
                        throw new NotRightHarmonyException();
                    possibleStupens.Add((basis + 2) % 7);
                    possibleStupens.Add((basis + 4) % 7);
                    possibleStupens.Add((basis + 6) % 7);
                    possibleStupens.Add(basis);
                    break;
                case "43":
                    //если oN не в басу, но при этом занимает ступень, что должна быть в басу,
                    //то значит, мы не правильно подобрали функцию  
                    if ((ourNote.getVoice() != Constants.BASS) && (ourNote.getStupen() == ((basis + 4) % 7)))
                        throw new NotRightHarmonyException();
                    possibleStupens.Add((basis + 4) % 7);
                    possibleStupens.Add((basis + 6) % 7);
                    possibleStupens.Add(basis);
                    possibleStupens.Add((basis + 2) % 7);
                    break;
                case "2":
                    //если oN не в басу, но при этом занимает ступень, что должна быть в басу,
                    //то значит, мы не правильно подобрали функцию  
                    if ((ourNote.getVoice() != Constants.BASS) && (ourNote.getStupen() == ((basis + 6) % 7)))
                        throw new NotRightHarmonyException();
                    possibleStupens.Add((basis + 6) % 7);
                    possibleStupens.Add(basis);
                    possibleStupens.Add((basis + 2) % 7);
                    possibleStupens.Add((basis + 4) % 7);
                    break;
            }

            if (!isHarmonyRightForOurNote(ourNote, possibleStupens))
                throw new NotRightHarmonyException();
            
            return possibleStupens;
        }

        //проверка на принодлежность заданной ноты ourNote к гармонии, которую мы строим 
        private static bool isHarmonyRightForOurNote(Note ourNote, List<int> possibleStupen)
        {
            return possibleStupen.Contains(ourNote.getStupen());
        }

	}
}
